home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / arc43.lbr / ARCUNP.MQC / arcunp.mac
Text File  |  1985-10-30  |  6KB  |  171 lines

  1. /*  ARC - Archive utility - ARCUNP
  2.  
  3. $define(tag,$$segment(@1,$$index(@1,=)+1))#
  4. $define(version,Version $tag(
  5. TED_VERSION DB =3.06), created on $tag(
  6. TED_DATE DB =06/25/85) at $tag(
  7. TED_TIME DB =11:11:34))#
  8. $undefine(tag)#
  9.     $version
  10.  
  11. (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  12.  
  13.     By:  Thom Henderson
  14.  
  15.     Description:
  16.          This file contains the routines used to expand a file
  17.          when taking it out of an archive.
  18.  
  19.     Language:
  20.          Computer Innovations Optimizing C86
  21. */
  22. #include <stdio.h>
  23. #include "arc.h"
  24.  
  25. /* stuff for repeat unpacking */
  26.  
  27. #define DLE 0x90                       /* repeat byte flag */
  28.  
  29. static int state;                      /* repeat unpacking state */
  30.  
  31. /* repeat unpacking states */
  32.  
  33. #define NOHIST 0                       /* no relevant history */
  34. #define INREP 1                        /* sending a repeated value */
  35.  
  36. static int crcval;                     /* CRC check value */
  37. static long size;                      /* bytes to read */
  38.  
  39. int unpack(f,t,hdr)                    /* unpack an archive entry */
  40. FILE *f, *t;                           /* source, destination */
  41. struct heads *hdr;                     /* pointer to file header data */
  42. {
  43.     int c;                             /* one char of stream */
  44.  
  45.     /* setups common to all methods */
  46.  
  47.     crcval = 0;                        /* reset CRC check value */
  48.     size = hdr->size;                  /* set input byte counter */
  49.     state = NOHIST;                    /* initial repeat unpacking state */
  50.  
  51.     /* use whatever method is appropriate */
  52.  
  53.     switch(hdrver)                     /* choose proper unpack method */
  54.     {
  55.     case 1:                            /* standard packing */
  56.     case 2:
  57.          while((c=getc_unp(f))!=EOF)
  58.               putc_unp(c,t);
  59.          break;
  60.  
  61.     case 3:                            /* non-repeat packing */
  62.          while((c=getc_unp(f))!=EOF)
  63.               putc_ncr(c,t);
  64.          break;
  65.  
  66.     case 4:                            /* Huffman squeezing */
  67.          init_usq(f);
  68.          while((c=getc_usq(f))!=EOF)
  69.               putc_ncr(c,t);
  70.          break;
  71.  
  72.     case 5:                            /* Lempel-Zev compression */
  73.          init_ucr();
  74.          while((c=getc_ucr(f))!=EOF)
  75.               putc_unp(c,t);
  76.          break;
  77.  
  78.     case 6:                            /* Lempel-Zev plus non-repeat */
  79.          init_ucr();
  80.          while((c=getc_ucr(f))!=EOF)
  81.               putc_ncr(c,t);
  82.          break;
  83.  
  84.     default:                           /* unknown method */
  85.          if(warn)
  86.          {    printf("I don't know how to unpack file %s\n",hdr->name);
  87.               printf("I think you need a newer version of ARC\n");
  88.          }
  89.          fseek(f,hdr->size,1);         /* skip over bad file */
  90.          return 1;                     /* note defective file */
  91.     }
  92.  
  93.     /* cleanups common to all methods */
  94.  
  95.     if(crcval!=hdr->crc)
  96.     {    if(warn)
  97.               printf("WARNING: File %s fails CRC check\n",hdr->name);
  98.          return 1;                     /* note defective file */
  99.     }
  100.     return 0;                          /* file is okay */
  101. }
  102.  
  103. /*  This routine is used to put bytes in the output file.  It also
  104.     performs various housekeeping functions, such as maintaining the
  105.     CRC check value.
  106. */
  107.  
  108. static putc_unp(c,t)                   /* output an unpacked byte */
  109. char c;                                /* byte to output */
  110. FILE *t;                               /* file to output to */
  111. {
  112.     crcval = addcrc(crcval,c);         /* update the CRC check value */
  113.  
  114.     if(t)                              /* if we really have a file */
  115.          if(fputc(c,t)==EOF)           /* then make sure this works */
  116.               abort("Write fail (disk full?)");
  117. }
  118.  
  119. /*  This routine is used to decode non-repeat compression.  Bytes are
  120.     passed one at a time in coded format, and are written out uncoded.
  121.     The data is stored normally, except that runs of more than two
  122.     characters are represented as:
  123.  
  124.          <char> <DLE> <count>
  125.  
  126.     With a special case that a count of zero indicates a DLE as data,
  127.     not as a repeat marker.
  128. */
  129.  
  130. static putc_ncr(c,t)                   /* put NCR coded bytes */
  131. unsigned char c;                       /* next byte of stream */
  132. FILE *t;                               /* file to receive data */
  133. {
  134.     static int lastc;                  /* last character seen */
  135.  
  136.     switch(state)                      /* action depends on our state */
  137.     {
  138.     case NOHIST:                       /* no previous history */
  139.          if(c==DLE)                    /* if starting a series */
  140.               state = INREP;           /* then remember it next time */
  141.          else putc_unp(lastc=c,t);     /* else nothing unusual */
  142.          return;
  143.  
  144.     case INREP:                        /* in a repeat */
  145.          if(c)                         /* if count is nonzero */
  146.               while(--c)               /* then repeatedly ... */
  147.                    putc_unp(lastc,t);  /* ... output the byte */
  148.          else putc_unp(DLE,t);         /* else output DLE as data */
  149.          state = NOHIST;               /* back to no history */
  150.          return;
  151.  
  152.     default:
  153.          abort("Bad NCR unpacking state (%d)",state);
  154.     }
  155. }
  156.  
  157. /*  This routine provides low-level byte input from an archive.  This
  158.     routine MUST be used, as end-of-file is simulated at the end of
  159.     the archive entry.
  160. */
  161.  
  162. int getc_unp(f)                        /* get a byte from an archive */
  163. FILE *f;                               /* archive file to read */
  164. {
  165.     if(!size)                          /* if no data left */
  166.          return EOF;                   /* then pretend end of file */
  167.  
  168.     size--;                            /* deduct from input counter */
  169.     return fgetc(f);                   /* and return the next byte */
  170. }
  171.